<?php

namespace Core\Common\Base;

use Core\Common\Model\CapsuleManager as Capsule;

/**
 * Description of Config
 *
 * @author baiyang
 */
class Config
{
    public static $config = null;
    public static $pool = null;
    public static $tables = null;
    private static $lastReloadTime = 0; // 上次配置加载时间，每个Worker之间的时间是相互独立的

    public static function flush()
    {
        self::$pool = null;
        self::$tables = null;
        self::$config = null;
    }

    /**
     * 解析app-<env>.ini
     * @return null
     */
    public static function init()
    {
        if (!ConfigSource::needReload(self::$pool, self::$lastReloadTime)) {
            // 配置没有任何变动
            return;
        }

        $content = ConfigSource::getAppConfig();
        if (empty($content)) {
            return;
        }

        self::$lastReloadTime = microtime(true);
        $result = new \stdClass();
        $retArr = [];
        foreach ($content as $k => $v) {
            $tmp = explode('.', $k);
            $cur = &$result;
            $arr = &$retArr;
            foreach ($tmp as $part) {
                if (!isset($cur->{$part})) {
                    $cur->{$part} = new \stdClass();
                    $arr[$part] = null;
                }
                $cur = &$cur->{$part};
                $arr = &$arr[$part];
            }
            $cur = $v;
            $arr = $v;
        }
        self::$config = $result;
        self::$pool = $retArr;
        self::initEloquent();
    }

    /**
     * 初始化ORM
     * @return null
     */
    private static function initEloquent()
    {
        if (empty(self::$pool['all_database_connection_names'])) {
            return;
        }
        $names = explode(',', self::$pool['all_database_connection_names']);
        $capsule = new Capsule();
        foreach ($names as $name) {
            if (empty($name)) {
                continue;
            }
            $name = trim($name);
            if (empty($name)) {
                continue;
            }
            $dbConfig = self::$pool['database'][$name];
            if (isset($dbConfig['read']['host'])) {
                $readDbs = explode(',', $dbConfig['read']['host']);
                $dbConfig['read']['host'] = array_map('trim', $readDbs);
            }
            $capsule->addConnection($dbConfig, $name);
        }
        $capsule->setAsGlobal();
        $capsule->bootEloquent();
    }

    public static function getMysql($name = '')
    {
        self::init();
        $section = 'database';
        if ($name) {
            if (isset(self::$pool[$section][$name])) {
                return self::$pool[$section][$name];
            }
            if (isset(self::$pool[$section]['*'])) {
                return self::$pool[$section]['*'];
            }
            return [];
        }
        return self::$pool[$section];
    }

    /**
     * 获取Redis配置
     * @return array
     */
    public static function getRedis($name = '')
    {
        self::init();
        $section = 'redis';
        if ($name) {
            $name = self::getNameMap($section, $name);
            if (isset(self::$pool[$section][$name])) {
                return self::$pool[$section][$name];
            }
            if (isset(self::$pool[$section]['*'])) {
                return self::$pool[$section]['*'];
            }
            return [];
        }
        return self::$pool[$section];
    }

    /**
     * 获取Redis配置
     * @return array
     */
    public static function getJaguar($name = '')
    {
        self::init();
        $section = 'jaguar';
        if ($name) {
            $name = self::getNameMap($section, $name);
            if (isset(self::$pool[$section][$name])) {
                return self::$pool[$section][$name];
            }
            if (isset(self::$pool[$section]['*'])) {
                return self::$pool[$section]['*'];
            }
            return [];
        }
        return self::$pool[$section];
    }

    /**
     * 获取数据库中各表的分表配置情况
     * @return type
     */
    public static function getTables()
    {
        if (!is_null(self::$tables)) {
            return self::$tables;
        }
        $tableJsonFile = CORE_CONFIG_PATH . 'tables-' . CORE_ENV . '.json';
        if (!defined('CORE_CONFIG_PATH') || !file_exists($tableJsonFile)) {
            self::$tables = [];
            return self::$tables;
        }
        $detail = json_decode(trim(file_get_contents($tableJsonFile)), true);
        self::$tables = $detail;
        return self::$tables;
    }

    public static function getService()
    {
        if (file_exists(CORE_CONFIG_PATH . 'swoole-' . CORE_ENV . '.ini')) {
            return parse_ini_file(CORE_CONFIG_PATH . 'swoole-' . CORE_ENV . '.ini');
        }
        if (file_exists(CORE_CONFIG_PATH . 'swoole.ini')) {
            return parse_ini_file(CORE_CONFIG_PATH . 'swoole.ini');
        }
        return [];
    }

    /**
     * 获取框架swoole所需要的配置文件
     * @return array|bool
     */
    public static function getSwooleServerConfig()
    {
        return self::getService();
    }

    /**
     * 获取代码中的库名=>实际库名的映射
     * @param string $resourceType mysql, redis, etc
     * @param string $name
     * @return mixed
     */
    public static function getNameMap($resourceType, $name)
    {
        if (class_exists('\App\Config\Common') && defined('\App\Config\Common::MAP_' . ucwords($resourceType))) {
            $map = constant('\App\Config\Common::MAP_' . ucwords($resourceType));
            if (isset($map[$name])) {
                return $map[$name];
            }
            return $name;
        }
        return $name;
    }

    /**
     * 读取app.ini中的$key开头的配置
     * @return stdClass
     */
    public static function getConfig($key = '')
    {
        self::init();
        if (empty($key)) {
            return self::$config;
        }
        $arr = explode('.', $key);
        $tmp = self::$config;
        foreach ($arr as $tmpKey) {
            if (!isset($tmp->{$tmpKey})) {
                return null;
            }
            $tmp = $tmp->{$tmpKey};
        }
        return $tmp;
    }

    /**
     *
     * @return mixed
     */
    public static function config($key = '')
    {
        self::init();
        if (empty($key)) {
            return self::$pool;
        }
        $arr = explode('.', $key);
        $tmp = self::$pool;
        foreach ($arr as $tmpKey) {
            if (!isset($tmp[$tmpKey])) {
                return null;
            }
            $tmp = $tmp[$tmpKey];
        }
        return $tmp;
    }
}
